﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.Diagnostics;
using IOPath = System.IO.Path;
using Microsoft.Office.OneNote.Interop;

namespace Microsoft.Office.OneNote
{
    public abstract class OneNoteFolder : OneNoteHierarchyObject, IOneNoteObjectWithChildren
    {
        internal static readonly OneNoteProperty NameProperty = OneNoteProperty.Register(
            "name", typeof(String), typeof(OneNoteFolder));

        internal static readonly OneNoteProperty PathProperty = OneNoteProperty.Register(
            "path", typeof(String), typeof(OneNoteFolder));

        private Boolean _storageInitialized;
        private OneNoteHierarchyObjectStorage _storage;

        internal OneNoteFolder(OneNoteObjectId id)
            : base(id)
        {
            _storage = new OneNoteHierarchyObjectStorage(this);
        }

        public string Name
        {
            get { return GetValue<String>(NameProperty); }
        }

        public string Path
        {
            get { return GetValue<String>(PathProperty); }
        }

        public bool Delete(OneNoteHierarchyObject obj)
        {
            return _storage.Delete(obj);
        }

        public void UpdateRecursive()
        {
            CheckValid();

            XDocument document = GetHierarchy(HierarchyScope.Pages);
            OneNoteSchema.Deserialize(this, document.Root);
        }

        internal OneNoteHierarchyObjectStorage Storage
        {
            get 
            {
                CheckValid();
                return _storage; 
            }
        }

        internal bool IsDescendantOf(OneNoteFolder potentialAncestor)
        {
            Contract.RequiresNotNull(potentialAncestor, "potentialAncestor");

            return IsDescendantOf(potentialAncestor.Path);
        }

        internal bool IsDescendantOf(string potentialAncestorPath)
        {
            return PathHelper.IsDescendantOf(Path, potentialAncestorPath);
        }

        internal bool IsAncestorOf(OneNoteFolder potentialDescendant)
        {
            Contract.RequiresNotNull(potentialDescendant, "potentialDescendant");

            return IsAncestorOf(potentialDescendant.Path);
        }

        internal bool IsAncestorOf(string potentialDescendantPath)  
        {
            return PathHelper.IsAncestorOf(Path, potentialDescendantPath);
        }

        internal bool IsAncestorOf(string potentialDescendantPath, out string relativePath)
        {
            return PathHelper.IsAncestorOf(Path, potentialDescendantPath, out relativePath);
        }

        internal void EnsureStorageInitialized()
        {
            CheckValid();

            if (!_storageInitialized && _storage.Count == 0)
            {
                Update();
            }

            _storageInitialized = true;
        }

        internal override HierarchyScope UpdateScope
        {
            get { return HierarchyScope.Children; }
        }

        internal sealed override void OnHierarchyChanged()
        {
            _storage.UpdateHierarchy(Hierarchy);
        }

         void IOneNoteObjectWithChildren.UpdateFrom(IEnumerable<XElement> elements)
        {
            _storage.UpdateFrom(elements);
            HasConflicts |= _storage.HasConflicts;
        }
    }
}
